package com.zmn.brs.utils;

import cn.hutool.core.io.IoUtil;
import com.zmn.common.utils.string.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.lionsoul.ip2region.DataBlock;
import org.lionsoul.ip2region.DbConfig;
import org.lionsoul.ip2region.DbSearcher;
import org.lionsoul.ip2region.Util;
import org.springframework.core.io.ClassPathResource;

import java.io.*;
import java.lang.reflect.Method;

/**
 * 类描述：ip地址工具类
 *
 * @author xujie
 * @since 2021/03/16 14:36
 */
@Slf4j
public class IPUtil {

    private static final String TAG = "ip地址工具类";

    /**
     * 根据ip地址获取城市信息
     * @param ip ip地址
     * @return 城市信息
     * @author xujie
     * @since 2021/03/16 15:30
     */
    public static String getCityInfo(String ip) {

        if (!Util.isIpAddress(ip)) {
            log.error("[{}], 根据ip地址获取城市信息，Error: Invalid ip address", TAG);
        }
        // 获取ip库路径
        ClassPathResource classPathResource = new ClassPathResource("data/ip2region.db");
        if (classPathResource.getClassLoader() == null){
            log.error("[{}], 根据ip地址获取城市信息，ip2region.db 文件不存在。", TAG);
            return null;
        }
        InputStream inputStream;
        try {
            inputStream = classPathResource.getInputStream();
        } catch (IOException e) {
            log.error("[{}], 根据ip地址获取城市信息，getInputStream() is Exception: {}", TAG, e.getMessage(), e);
            return null;
        }
        byte[] bytes = IoUtil.readBytes(inputStream);
        // 查询算法：B-tree、Binary、Memory
        int algorithm = DbSearcher.MEMORY_ALGORITYM;
        try {
            DbSearcher searcher = new DbSearcher(new DbConfig(), bytes);
            String value = AlgorithmEnum.getMethodByAlgorithm(algorithm);
            if (StringUtil.isBlank(value)){
                log.error("[{}], 根据ip地址获取城市信息，Error: algorithm is null", TAG);
                return null;
            }
            Method method = searcher.getClass().getMethod(value, String.class);
            DataBlock dataBlock  = (DataBlock) method.invoke(searcher, ip);
            return dataBlock.getRegion();
        } catch (Exception e) {
            log.error("[{}], 根据ip地址获取城市信息，异常：{}", TAG, e.getMessage(), e);
            return null;
        }
    }

    public enum AlgorithmEnum {

        /**
         * 查询算法
         */
        B_TREE_SEARCH(DbSearcher.BTREE_ALGORITHM,"btreeSearch"),
        BINARY_SEARCH(DbSearcher.BINARY_ALGORITHM,"binarySearch"),
        MEMORY_SEARCH(DbSearcher.MEMORY_ALGORITYM,"memorySearch");

        /** 算法类型 **/
        private final int algorithm;
        /** 使用算法名称 **/
        private final String value;

        public static String getMethodByAlgorithm(int algorithm){
            for (AlgorithmEnum algorithmEnum: AlgorithmEnum.values()){
                if (algorithmEnum.algorithm == algorithm){
                    return algorithmEnum.value;
                }
            }
            return null;
        }

        AlgorithmEnum(int algorithm, String value) {
            this.algorithm = algorithm;
            this.value = value;
        }
    }

}
